<?php
declare (strict_types = 1);

namespace app\common\command;

use app\common\model\user\Assignment;
use app\common\validate\User;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use app\common\model\user\Permission as PermissionModel;
use think\exception\ValidateException;
use think\facade\Db;
use app\common\model\user\User as UserModel;

class Member extends Command
{
    //角色
    const ROLE_ADMIN = 'admin';
    const ROLE_AUTHOR = 'author';

    protected function configure()
    {
        // 指令配置
        $this->setName('member')
            ->addArgument('action', Argument::OPTIONAL, "[create | update | delete] Edit member")
            ->addOption('role', null, Option::VALUE_REQUIRED, '['.static::ROLE_ADMIN.' | '.static::ROLE_AUTHOR.'] user role')
            ->addOption('username', null, Option::VALUE_REQUIRED, 'user name')
            ->addOption('password', null, Option::VALUE_REQUIRED, 'user password')
            ->addOption('email', null, Option::VALUE_REQUIRED, 'user email')
            ->setDescription('Edit member command');
    }

    protected function execute(Input $input, Output $output)
    {
        // 指令输出
        $action = $input->getArgument('action') ?: 'create';
        $action = strtolower($action);

        //选项
        $username = $input->getOption('username') ?: '';
        $password = $input->getOption('password') ?: '';
        $email = $input->getOption('email') ?: '';

        $params = ['username'=>$username,'password'=>$password,'email'=>$email];

        //角色
        $role = $input->getOption('role') ?: '';

        switch ($action){
            case 'create':
                $this->create($output, $params, $role);
                break;
            case 'update':
                $this->update($output, $params, $role);
                break;
            case 'delete':
                $this->delete($output, $params, $role);
                break;
            default:
                $output->writeln('action param error.');
                break;
        }

    }

    /**
     * 创建用户
     * @param Output $output
     * @param array $params
     * @param string $role
     * @return bool
     */
    private function create(Output $output, array $params, string $role){

        if (empty($params['password'])) throw new ValidateException('Password cannot be empty');

        validate(User::class)->check($params);

        Db::transaction(function () use ($output, $params, $role) {

            $user = new UserModel();
            $user->save([
                'username'  => $params['username'],
                'password_hash'=>UserModel::generatePasswordHash($params['password']),
                'email' =>  $params['email']
            ]);

            $this->assignment((int) $user->id, $role);


        });
        //初始化完成
        $output->writeln('create user success.');
        return true;
    }

    /**
     * 指派角色
     * @param int $user_id
     * @param string $role
     * @return bool|\think\Collection
     * @throws \Exception
     */
    private function assignment(int $user_id, string $role = ''){
        //确保当前用户没有指派
        Assignment::where(['user_id'=>$user_id])->delete();

        //如果不需要指派角色 直接返回
        if (empty($role)) return true;

        //获取所有存在角色
        $rolesData = PermissionModel::where([])->column('id','name');


        //生成指派信息
        $assignment = [];
        $roles = explode(',',$role);
        foreach ($roles as $k => $v){
            if (empty($v)) continue;

            if ($v === static::ROLE_ADMIN){
                $assignment[] = [
                    'user_id' => $user_id,
                    'permission_id' => $rolesData[Permission::ROLE_ADMIN]
                ];
            }
            if ($v === static::ROLE_AUTHOR){
                $assignment[] = [
                    'user_id' => $user_id,
                    'permission_id' => $rolesData[Permission::ROLE_AUTHOR]
                ];
            }
        }

        //保存
        return (new Assignment())->saveAll($assignment);

    }


    /**
     * 编辑用户
     * @param Output $output
     * @param array $params
     * @param string $role
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function update(Output $output, array $params, string $role){
        if (empty($params['username'])) throw new ValidateException('username cannot be empty');

        $user = UserModel::where(['username'=>$params['username']])->find();
        $params = array_merge($params, ['id'=>$user->id]);

        validate(User::class)->check($params);

        if ($params['password']){
            $params = array_merge($params, ['password_hash'=>UserModel::generatePasswordHash($params['password'])]);
        }

        Db::transaction(function () use ($user, $params, $role) {


            $user->save($params);

            $this->assignment((int) $user->id, $role);


        });
        //初始化完成
        $output->writeln('update user success.');
        return true;
    }

    /**
     * 删除用户
     * @param Output $output
     * @param array $params
     * @param string $role
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function delete(Output $output, array $params, string $role){
        if (empty($params['username'])) throw new ValidateException('username cannot be empty');

        $user = UserModel::where(['username'=>$params['username']])->find();

        Db::transaction(function () use ($user, $params, $role) {


            $user->delete();

            $this->assignment((int) $user->id);

        });
        //初始化完成
        $output->writeln('delete user success.');
        return true;
    }



}
